使用捏合操纵器可以使用户在 Kanzi 应用程序中缩放和旋转节点。为了计算缩放和旋转节点的量,捏合手势持续跟踪设备屏幕上两个手指之间的位置和位置。
使用多击操纵器可以使用户在 Kanzi 应用程序中多击或多敲节点。您可在多击操纵器中设置轻敲次数和Kanzi 两次轻敲之间的最长时间,以将多次轻敲解释为多击手势。
这一步中首先使用捏合手势实现地图的缩放和旋转。然后使用多击操纵器实现地图位置、缩放水平和旋转角度的重置。
在 Android 设备上部署该教程应用程序,因为捏合手势需要多击支持。
这一节中,您将创建和使用捏合操纵器,在用户捏合地图时缩放和旋转地图。
要缩放和旋转地图:
PanZoomTap
类的私有部分定义捏合消息的处理程序:private: ... //为PinchManipulator::StartedMessage
消息定义处理程序,该消息来自 //具有可生成捏合消息的输入操纵器的 2D 节点。 //此处理程序可为捏合手势准备 2D 节点。 void onPinchStarted(PinchManipulator::StartedMessageArguments& messageArguments) { //从消息参数获得用户捏合的节点。 Node2DSharedPtr mapNode = dynamic_pointer_cast<Node2D>(messageArguments.getSource()); //存储渲染变换 (Render Transformation) 属性缩放 (Scale) 属性字段的初始值。 SRTValue2D nodeTransform = mapNode->getRenderTransformation(); m_pinchInitialScaleFactor = nodeTransform.getScale().getX() - 1.0f; //根据应用程序屏幕的大小计算最小比例值。 ScreenSharedPtr screen = getScreen(); m_minScale = max(getScreen()->getActualWidth() / mapNode->getActualWidth(), screen->getActualHeight() / mapNode->getActualHeight()); } //为PinchManipulator::MovedMessage
消息定义处理程序,该消息来自 //具有可生成捏合消息的输入操纵器的 2D 节点。 //这样可按捏合手势的量缩放和旋转 2D 节点。 void onPinchMoved(PinchManipulator::MovedMessageArguments& messageArguments) { //从消息参数获得用户捏合的节点。 Node2DSharedPtr mapNode = dynamic_pointer_cast<Node2D>(messageArguments.getSource()); //从消息参数获取比例和旋转。 float scaleDelta = messageArguments.getScale(); float rotateDelta = messageArguments.getRotation(); //通过添加初始比例到捏合值计算比例。 //限制比例,使得地图不小于应用程序屏幕的大小。 float scale = max(m_minScale, scaleDelta + m_pinchInitialScaleFactor); //获取 Map 节点的渲染变换 (Render Transformation) 属性。 SRTValue2D mapRenderSRT = mapNode->getRenderTransformation(); //应用旋转。 mapRenderSRT.rotate(rotateDelta); //应用比例。 mapRenderSRT.setScale(Vector2(scale, scale)); //获取 Map 节点的世界变换。 //在该教程的下一步使用。 Matrix3x3 mapWorldTransform = mapNode->getWorldTransform(); SRTValue2D mapWorldSRT = *SRTValue2D::create(mapWorldTransform); //应用新渲染变换到 Map 节点。 mapNode->setRenderTransformation(mapRenderSRT); } //为捏合手势的初始比例因子定义成员变量。 float m_pinchInitialScaleFactor; //为最小比例值定义成员变量。 float m_minScale; };
PanZoomTap
类的公有部分开始处添加构造函数,并为该捏合手势设置初始比例因子:public: PanZoomTap() : m_pinchInitialScaleFactor(0.0f) { } ...
onProjectLoaded
() 函数中创建 PinchManipulator
操纵器并订阅 Map 节点的消息:virtual void onProjectLoaded() KZ_OVERRIDE { ... //创建生成捏合消息的输入操纵器。 PinchManipulatorSharedPtr pinchManipulator = PinchManipulator::create(domain); //添加输入操纵器到 Map 节点。 mapNode->addInputManipulator(pinchManipulator); //订阅 Map 节点的PinchManipulator::StartedMessage
消息。 // PinchManipulator 在用户在 Map 节点按下两根手指时生成此消息。 mapNode->addMessageHandler(PinchManipulator::StartedMessage, bind(&PanZoomTap::onPinchStarted, this, placeholders::_1)); //订阅 Map 节点的PinchManipulator::MovedMessage
消息。 //PinchManipulator
在超出比例或旋转阈值时生成此消息, //并在被跟踪触摸在更新之间移动时生成此消息。 mapNode->addMessageHandler(PinchManipulator::MovedMessage, bind(&PanZoomTap::onPinchMoved, this, placeholders::_1)); }
在您的 Android 设备上使用捏合手势缩放和旋转地图。
地图围绕其中心点旋转,因为 Map 节点的原点被设置为中心。
在本节中,您将使用多击操纵器在用户双敲地图时重置地图的位置、缩放水平和旋转角度。
要重置位置、缩放水平和旋转:
PanZoomTap
类的私有部分定义多击消息的处理程序:private:
...
//为 MultiClickManipulator::MultiClickMessage
消息定义处理程序,该消息来自
//具有可在用户双敲节点时生成多击消息的输入操纵器的节点。
void onNodeDoubleTapped(MultiClickManipulator::MultiClickMessageArguments& messageArguments)
{
//从消息参数获取用户双敲的节点。
Node2DSharedPtr mapNode = dynamic_pointer_cast<Node2D>(messageArguments.getSource());
//移除该节点的渲染变换 (Render Transformation) 属性。
//这样即可重置 Map 节点的位置、缩放水平和旋转角度。
mapNode->removeLocalValue(Node2D::RenderTransformationProperty);
}
...
};
onProjectLoaded
() 函数中创建并配置 MultiClickManipulator
操纵器并订阅 Map 节点的消息:virtual void onProjectLoaded() KZ_OVERRIDE { ... //创建生成多击消息的输入操纵器。 MultiClickManipulatorSharedPtr multiClickManipulator = MultiClickManipulator::create(domain); //添加输入操纵器到Map 节点。 mapNode->addInputManipulator(multiClickManipulator); //默认情况下,输入操纵器将两次轻敲识别为双敲手势。 //要使用不同次数的轻敲,使用MultiClickManipulator::setExpectedClicks
函数。 //例如,将输入操纵器设置为将三次轻敲识别为多击手势,将 3 传递给该函数。 // multiClickManipulator->setExpectedClicks(3); //将双敲超时设置为 300 ms。如果两次轻敲之间的时间未超出该值, //输入操纵器将这些轻敲识别为双敲手势。默认超时为 250 ms。 multiClickManipulator->setTimeout(chrono::milliseconds(300)); //订阅Map 节点的MultiClickManipulator::MultiClickMessage
消息。 //MultiClickManipulator
操纵器在用户双敲节点时生成此消息。 mapNode->addMessageHandler(MultiClickManipulator::MultiClickMessage, bind(&PanZoomTap::onNodeDoubleTapped, this, placeholders::_1)); }
要详细了解捏合操纵器,请参阅使用捏合操纵器。
要详细了解多击操纵器,请参阅使用多击操纵器。
要详细了解部署 Kanzi 应用程序到 Android,请参阅部署 Kanzi 应用程序到 Android。